#pragma once

#include "ICollection.h"
#include "IEnumerator.h"
#include <memory.h>

namespace Framework
{
	template <class T>
	class List
		: public ICollection<T>
	{
	public:
		class Enumerator
			: public IEnumerator<T>
		{
		public:
			Enumerator(List* list)
				: m_List(list)
				, m_CurrentIndex(0)
			{
			}

			~Enumerator()
			{
			}

			bool MoveNext()
			{
				return (m_CurrentIndex++ < m_List->Count());
			}

			T Current()
			{
				return m_List->ElementOf(m_CurrentIndex);
			}

			bool IsValid()
			{
				return (m_List != NULL);
			}
		protected:
			List* m_List;
			UInt32 m_CurrentIndex;
		};
		List()
			: m_Capacity(4)
			, m_Size(0)
		{
			m_Array = new T[m_Capacity];
		}
		List(const List& other)
		{
			m_Capacity = other.Count();
			m_Size = m_Capacity;
			m_Array = new T[m_Capacity];
			CopyFrom(other);
		}
		List(const ICollection<T>& other)
		{
			m_Capacity = other.Count();
			m_Size = m_Capacity;
			m_Array = new T[m_Capacity];
			CopyFrom(other);
		}
		List(UInt32 capacity)
			: m_Capacity(capacity)
			, m_Size(0)
		{
			m_Array = new T[m_Capacity];
		}
		List(T* array, UInt32 elementCount)
		{
			m_Capacity = elementCount;
			m_Size = m_Capacity;
			m_Array = new T[elementCount];
			memcpy(&m_Array, &array, elementCount * sizeof(T));
		}
		~List()
		{
			memset(&m_Array, 0, m_Size * sizeof(T));
		}
		UInt32 Add(T item)
		{
			if(m_Size >= m_Capacity)
				IncreaseCapacity(m_Size * 2);
			m_Array[m_Size] = item;
			return m_Size++;
		}

		bool Remove(T item)
		{
			for(UInt32 i=0; i < Count(); ++i)
			{
				if(!memcmp(&m_Array[i], &item, sizeof(T)))
				{
					memset(&m_Array[i], 0, sizeof(T));
					return true;
				}
			}
			return false;
		}

		bool Contains(T item)
		{
			for(UInt32 i=0; i < Count(); ++i)
			{
				if(!memcmp(&m_Array[i], &item, sizeof(T)))
					return true;
			}
			return false;
		}

		void CopyFrom(ICollection<T>& other)
		{
			IEnumerator<T>* e = other.GetEnumerator();
			while(e->MoveNext())
				Add(e->Current());
		}

		void CopyFrom(T* array, UInt32 elementCount)
		{
			for(UInt32 i=0; i < elementCount; ++i)
				Add(array[i]);
		}

		UInt32 Count()
		{
			return m_Size;
		}

		T ElementOf(UInt32 index) { return m_Array[index]; }
		T operator [](UInt32 index) { return m_Array[index]; }

		Enumerator* GetEnumerator() { return new Enumerator(this); }
	protected:
		void IncreaseCapacity(UInt32 capacity)
		{
			m_Capacity = capacity;
			T* array = new T[m_Capacity];
			if(m_Size > capacity)
				m_Size = capacity;
			memcpy(array, m_Array, m_Size * sizeof(T));
			delete[] m_Array;
			m_Array = array;
		}
		UInt32 m_Capacity;
		UInt32 m_Size;
		T* m_Array;
	};
};